package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * 面向切面编程
 */
//@Component //让spring创建该类的对象，保存到IOC容器中
//@Aspect  //表示该类是一个切面类，对目标方法进行增强
@Slf4j
public class TimeAspect6 {

//    //前置通知，在目标方法执行之前执行
//    @Before("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
//    public void before(){
//        log.info("前置通知before");
//    }
//
//    //后置通知/返回后通知，在目标方法执行之后且不出现异常时执行
//    @AfterReturning("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
//    public void afterReturning(){
//        log.info("后置通知afterReturning");
//    }
//
//    //异常通知，在目标方法执行之后且出现异常时执行
//    @AfterThrowing("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
//    public void afterThrowing(){
//        log.info("异常通知afterThrowing");
//    }
//
//    //最终通知，在目标方法执行之后无论是否出现异常都执行
//    @After("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
//    public void after(){
//        log.info("最终通知after");
//    }


    /**
     * @Around 环绕通知
     * @Around("")：写在方法上，表示该方法是一个通知方法，在方法内定义通知（要增强的逻辑代码）内容
     * execution(* com.itheima.service.impl.DeptServiceImpl.*(..)) :切点表达式，找出哪些类的哪些方法要增强，找切点。
     *  * ：任意一个返回值类型、任意一个包名、类名、方法名、任意一个参数类型
     *  .. ：表示任意多个任意类型的参数
     *
     * @param pjp
     * @return
     */
    @Around("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {

        //1. 获取目标对象类名
        String className = pjp.getTarget().getClass().getName();
        log.info("目标对象类名:{}",className);

        // 2.获取目标对象正在执行的方法的方法名
        Signature signature = pjp.getSignature();
        String methodName = signature.getName();
        log.info("方法签名:{}",signature);
        log.info("方法名:{}",methodName);

        // 3.获取参数值
        Object[] args = pjp.getArgs();
        log.info("参数值:{}",args);

        // 执行目标对象方法
        Object result = pjp.proceed();

        return result;


    }
}
